package me.boot.auth.spring.rbac;

import cn.hutool.core.collection.CollUtil;
import me.boot.auth.spring.AuthConst;
import me.boot.auth.spring.AuthMode;
import me.boot.auth.spring.propertites.AuthProperties;
import me.boot.auth.spring.service.UserService;
import me.boot.sys.entity.SysRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;

/**
 * File Name             :  UrlFilterInvocationSecurityMetadataSource
 *
 * @author :  sylar
 * @create :  2018/11/17
 * Description           :  该类的主要功能就是通过当前的请求地址，获取该地址需要的用户角色
 * Reviewed By           :
 * Reviewed On           :
 * Version History       :
 * Modified By           :
 * Modified Date         :
 * Comments              :
 * CopyRight             : COPYRIGHT(c) me.iot.com   All Rights Reserved
 * *******************************************************************************************
 */
@Component
public class MetadataSourceImpl implements FilterInvocationSecurityMetadataSource {

    @Autowired
    UserService userService;

    @Autowired
    AuthProperties authProperties;

    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        AuthMode mode = authProperties.getAuthMode();
        switch (mode) {
            case None:
                //不需要权限
                return null;
            case LoginOnly:
                //需要登录
                return SecurityConfig.createList(AuthConst.ROLE_LOGIN);
            case RBAC:
                FilterInvocation filterInvocation = (FilterInvocation) object;
                //获取请求地址
                String requestUrl = filterInvocation.getRequestUrl();
                List<SysRole> roles = userService.findByUrl(requestUrl, filterInvocation.getHttpRequest().getMethod());
                if (CollUtil.isEmpty(roles)) {
                    //返回null,不需要权限
                    return null;
                } else {
                    return buildAttrs(roles);
                }
            default:
                return null;
        }
    }

    private List<ConfigAttribute> buildAttrs(List<SysRole> roles) {
        String[] roleNames = roles.stream().map(SysRole::getName).toArray(String[]::new);
        return SecurityConfig.createList(roleNames);
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
}
